#include "estructuras.h"
#include <time.h>

/* produce FloorPan para eviar a cabina */

int main(int argc, char *argv[])
{
	srand(time(NULL));
	char mensaje[500];
	m_kanbanproduccion msg_kproduccion;
	m_kanbanentreprocesos msg_kprocesos;
	m_kanbanproveedor msg_kproveedor;
	m_kanbancompras msg_kcompras;
	t_stock stock_floor;

	int producidos, fentregar, temprcv;

	int colaE, colaI;
	key_t clave_colaE, clave_colaI;

	clave_colaE = ftok(DIRECTORIO, COLA_EXTERNA);
	clave_colaI = ftok(DIRECTORIO, COLA_INTERNA);

	if ( (colaE = msgget(clave_colaE, 0666)) < 0 )				/* Obtengo el ID de la cola */
	{
		sprintf(mensaje, "Error al obtener el ID de la cola Externa\n");
		write(fileno(stdout), mensaje, strlen(mensaje));
		exit(-1);
	}
	
	if ( (colaI = msgget(clave_colaI, 0666)) < 0 )				/* Obtengo el ID de la cola */
	{
		sprintf(mensaje, "Error al obtener el ID de la cola Interna\n");
		write(fileno(stdout), mensaje, strlen(mensaje));
		exit(-1);
	}

	/* Defino el stock a pie de maquina */
	stock_floor.stock = 32;						/* Cantidad de stock que puedo almacenar */
	stock_floor.stockMinimo = 4;
	stock_floor.stockLibre = rand()%stock_floor.stock + 1;
	stock_floor.estado = 0;						/* 0 sin Kanban Proveedor, 1 con Kanban Proveedor */		

	/* Armo el Kanban de Proveedor, para solicitar stock */
	msg_kproveedor.sector=getpid();
	msg_kproveedor.mtype=MSG_PROVEEDOR;
	msg_kproveedor.tugger=0;
	msg_kproveedor.darsena=0;
	msg_kproveedor.cantidadEntregada=0;
	//msg_kproveedor.fechaEntrega="0";
	msg_kproveedor.horaEntrega=0;
	msg_kproveedor.entregada=0;

	/* Armo la copia del Kanban de Proveedor para la Oficina de Compras */
	msg_kcompras.sector=getpid();
	msg_kcompras.mtype=MSG_OCOMPRAS;
	msg_kcompras.tugger=0;
	msg_kcompras.darsena=0;
	msg_kcompras.cantidadEntregada=0;
	//msg_kcompras.fechaEntrega="0";
	msg_kcompras.horaEntrega=0;
	msg_kcompras.entregada=0;

	sprintf(mensaje, "+---------------------------+\n");
	write(fileno(stdout), mensaje, strlen(mensaje));
	sprintf(mensaje, "| Stock libre inicial: %d\n", stock_floor.stockLibre);
	write(fileno(stdout), mensaje, strlen(mensaje));
	sprintf(mensaje, "+---------------------------+\n\n");
	write(fileno(stdout), mensaje, strlen(mensaje));

	while(1)
	{
		/* Espero Kanban de produccion con las cantidades a producir */
		if ( msgrcv(colaI, (m_kanbanproduccion *) &msg_kproduccion, sizeof(m_kanbanproduccion), MSG_FLOOR_PROD, 0) < 0 )
		{
			sprintf(mensaje, "Floor: Error al recibir el pedido de Cabina KProduccion\n");
			write(fileno(stdout), mensaje, strlen(mensaje));
			exit(-1);
		}

// le meto mi pid
		msg_kproduccion.sectorSiguiente = msg_kproduccion.sector;
		msg_kproduccion.sector = getpid();

		sprintf(mensaje, "+------------------------------------+\n");
		write(fileno(stdout), mensaje, strlen(mensaje));
		sprintf(mensaje, "| Floor: Recibi KProduccion de Cabina |\n");
		write(fileno(stdout), mensaje, strlen(mensaje));
		sprintf(mensaje, "+------------------------------------+\n");
		write(fileno(stdout), mensaje, strlen(mensaje));
		sprintf(mensaje, "Sector: %d\n", msg_kproduccion.sector);
		write(fileno(stdout), mensaje, strlen(mensaje));
		sprintf(mensaje, "Cantidad de floorpans a producir: %d\n\n", msg_kproduccion.cantVehiculos);
		write(fileno(stdout), mensaje, strlen(mensaje));

		/* Se producen 4 floors por auto */
		fentregar = msg_kproduccion.cantVehiculos * 4;

		for (producidos=1; producidos <= fentregar; producidos++)
		{		
			if ( msgrcv(colaI, (m_kanbanentreprocesos *) &msg_kprocesos, sizeof(m_kanbanentreprocesos), MSG_FLOOR_PROC, 0) < 0 )
			{
				sprintf(mensaje, "Floor: Error al recibir KEProcesos de Cabina\n");
				write(fileno(stdout), mensaje, strlen(mensaje));
				exit(-1);
			}

			sprintf(mensaje, "---------------------------------------------------------------\n");
			write(fileno(stdout), mensaje, strlen(mensaje));
			sprintf(mensaje, "Floor: Recibi de Cabina KEntreProcesos con nroSector: %ld\n", msg_kprocesos.nroSector);
			write(fileno(stdout), mensaje, strlen(mensaje));
			sprintf(mensaje, "nroVehiculo %d\n", msg_kprocesos.nroVehiculo);
			write(fileno(stdout), mensaje, strlen(mensaje));
			sprintf(mensaje, "codParte %d\n", msg_kprocesos.codParte);
			write(fileno(stdout), mensaje, strlen(mensaje));
			sprintf(mensaje, "nroOrden %d\n \n", msg_kprocesos.nroOrden);
			write(fileno(stdout), mensaje, strlen(mensaje));

			/*
				Verifico la cantidad de stock, si esta por debajo del minimo hago un pedido.
				Verifico tambien si el pedido ya esta hecho o no
			*/
			if ((stock_floor.stockMinimo >= stock_floor.stock - stock_floor.stockLibre) && (stock_floor.estado == 0))
			{
				msg_kproveedor.cantidad = stock_floor.stock - stock_floor.stockMinimo;

				sprintf(mensaje, "+----------------------------------+\n");
				write(fileno(stdout), mensaje, strlen(mensaje));
				sprintf(mensaje, "| Floor: Solicito Stock a Proveedor |\n");
				write(fileno(stdout), mensaje, strlen(mensaje));
				sprintf(mensaje, "+----------------------------------+\n");
				write(fileno(stdout), mensaje, strlen(mensaje));
				sprintf(mensaje, "Nivel de stock: %d\n", stock_floor.stock - stock_floor.stockLibre);
				write(fileno(stdout), mensaje, strlen(mensaje));
				sprintf(mensaje, "Solicito a proveedor %d\n\n", msg_kproveedor.cantidad);
				write(fileno(stdout), mensaje, strlen(mensaje));

				/* Marco el estado del Stock como que ya emiti un Kanban al Proveedor (para no repetir el pedido ) */
				stock_floor.estado = 1;

				if ( msgsnd(colaE, (m_kanbanproveedor *) &msg_kproveedor, sizeof(m_kanbanproveedor), 0) < 0 )
				{
					sprintf(mensaje, "Floor: Error al enviar a Proveedor\n");
					write(fileno(stdout), mensaje, strlen(mensaje));
					exit(-1);
				}
				
				msg_kcompras.cantidad = msg_kproveedor.cantidad;

				/* Mando copia del Kanban de Proveedores a la Oficina de Compras */
				if ( msgsnd(colaE, (m_kanbancompras *) &msg_kcompras, sizeof(m_kanbancompras), 0) < 0 )
				{
					sprintf(mensaje, "Floor: Error al enviar a Proveedor\n");
					write(fileno(stdout), mensaje, strlen(mensaje));
					exit(-1);
				}
			}

			/* Verifico si el Proveedor ya me entrego el stock que habia solicitado */
			if ( temprcv = msgrcv(colaE, (m_kanbanproveedor *) &msg_kproveedor, sizeof(m_kanbanproveedor), msg_kproveedor.sector, IPC_NOWAIT) != -1 )
			{
				stock_floor.stockLibre = stock_floor.stockLibre - msg_kproveedor.cantidadEntregada;
				stock_floor.estado = 0;

				sprintf(mensaje, "+---------------------------------+\n");
				write(fileno(stdout), mensaje, strlen(mensaje));
				sprintf(mensaje, "| Floor: Recibi Stock de Proveedor |\n");
				write(fileno(stdout), mensaje, strlen(mensaje));
				sprintf(mensaje, "+---------------------------------+\n");
				write(fileno(stdout), mensaje, strlen(mensaje));
				sprintf(mensaje, "Cantidad de piezas: %d\\nn", msg_kproveedor.cantidad);
				write(fileno(stdout), mensaje, strlen(mensaje));
			}
			if ( temprcv < 0 )
			{
				sprintf(mensaje, "Floor: Error al recibir KanbanProveedores\n");
				write(fileno(stdout), mensaje, strlen(mensaje));
				exit(-1);
			}

			/* Si llego al nivel cero de stock, me quedo frenado esperando que el Proveedor me conteste */
			if ((stock_floor.stockLibre == stock_floor.stock) && (stock_floor.estado == 1))
			{
				sprintf(mensaje, "Floor: No tengo stock, me bloqueo en espera\n\n");
				write(fileno(stdout), mensaje, strlen(mensaje));

				if ( msgrcv(colaE, (m_kanbanproveedor *) &msg_kproveedor, sizeof(m_kanbanproveedor), msg_kproveedor.sector, 0) < 0 )
				{
					sprintf(mensaje, "Floor: Error al recibir KProv de Proveedor\n");
					write(fileno(stdout), mensaje, strlen(mensaje));
					exit(-1);
				}
				stock_floor.estado = 0;
			}

			//modifico KanbanEntreProcesos y Produccion
			/* Comienzo el proceso de Produccion */
			stock_floor.stockLibre++;
			sprintf(mensaje, "Floor: Armando Floor %d de %d...\n", producidos, fentregar);
			write(fileno(stdout), mensaje, strlen(mensaje));
			sleep(rand()%2);
			sprintf(mensaje, "Floor: Stock disponible %d \n\n", stock_floor.stockLibre);
			write(fileno(stdout), mensaje, strlen(mensaje));


			msg_kprocesos.mtype = MSG_CABINA_FLOOR;
			sprintf(mensaje, "Floor: envio KanbanEntreProcesos a %d\n\n", msg_kprocesos.nroSector);
			write(fileno(stdout), mensaje, strlen(mensaje));

			if ( msgsnd(colaI, (m_kanbanentreprocesos *) &msg_kprocesos, sizeof(m_kanbanentreprocesos), 0) < 0 )
			{
				sprintf(mensaje, "Floor:Error al encolar kprocesos nro %d\n", msg_kprocesos.nroVehiculo);
				write(fileno(stdout), mensaje, strlen(mensaje));

		        	exit(-1);
			}
			sprintf(mensaje, "Floor:Cantidad de veces que se recibio y envio un EntreProcesos %d\n", producidos);
			write(fileno(stdout), mensaje, strlen(mensaje));
		}

		sprintf(mensaje, "Floor: Estoy listo para recibir otro Kanban de Produccion\n");
		write(fileno(stdout), mensaje, strlen(mensaje));
	}
}
